<?php
//   +----------------------------------------------------------------------
//   | Copyright (c) 2015-2025 http://www.hdphp.cn All rights reserved.
//   | Licensed ( http://www.hdphp.cn/licenses/ )
//   | Author: Jack <sophia2152@qq.com>
//   | 官方网址: http://www.hdphp.cn
//   | 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用。
//   | 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
//   +----------------------------------------------------------------------
namespace app\services\system;

use app\services\BaseServices;
use app\dao\system\SystemMenusDao;
use hdphp\exceptions\AdminException;
use hdphp\utils\Arr;

/**
 * Class：系统菜单服务
 * 创建人：Jack
 * 创建时间：2023/7/28 17:41
 * @package app\services\system
 * @mixin SystemMenusDao
 */
class SystemMenusServices extends BaseServices
{

    /**
     * SystemMenusServices constructor.
     * @param SystemMenusDao $dao
     */
    public function __construct(SystemMenusDao $dao)
    {
        $this->dao = $dao;
    }

    /**
     * 注释：获取后台菜单树型结构列表
     * 创建人：Jack
     * 创建时间：2023/8/1 10:39
     * @param array $where
     * @return array
     */
    public function getList(array $where)
    {
        $menusList = $this->dao->getMenusList($where);
        $menusList = $this->getMenusData($menusList);
        return get_tree_children($menusList);
    }


    /**
     * 注释：获取后台权限菜单和权限
     * 创建人：Jack
     * 创建时间：2023/7/29 7:21 PM
     * @param     $rouleId
     * @param int $level
     * @return array
     */
    public function getMenusList($rouleId, int $level)
    {
        /** @var SystemRoleServices $systemRoleServices */
        $systemRoleServices = app()->make(SystemRoleServices::class);
        $rules = $systemRoleServices->getRoleArray(['status' => 1, 'id' => $rouleId], 'rules');
        $rulesStr = Arr::unique($rules);
        $menusList = $this->dao->getMenusRoule(['route' => $level ? $rulesStr : '']);
        $unique = $this->dao->getMenusUnique(['unique' => $level ? $rulesStr : '']);
        return [Arr::getMenuIviewList($this->getMenusData($menusList)), $unique];
    }

    /**
     * 注释：获取菜单没有被修改器修改的数据
     * 创建人：Jack
     * 创建时间：2023/7/29 7:21 PM
     * @param $menusList
     * @return array
     */
    public function getMenusData($menusList)
    {
        $data = [];
        foreach ($menusList as $item) {
//            $item['expand'] = true;
            $item['selected'] = false;
            $item['title'] = $item['menu_name'];
            $item['menu_path'] = preg_replace('/^\/' . config('app.admin_prefix', 'admin') . '/', '', $item['menu_path']);
            $data[] = $item->getData();
        }

        return $data;
    }

    /**
     * 获取一条数据
     * @param int $id
     * @return mixed
     */
    public function find(int $id)
    {
        $menusInfo = $this->dao->get($id);
        if (!$menusInfo) {
            throw new AdminException('数据不存在');
        }
        $menu = $menusInfo->getData();
        $menu['pid'] = (int)$menu['pid'];
        $menu['auth_type'] = (int)$menu['auth_type'];
        $menu['is_header'] = (int)$menu['is_header'];
        $menu['is_show'] = (int)$menu['is_show'];
        $menu['is_show_path'] = (int)$menu['is_show_path'];
        if (!$menu['path']) {
            [$menuList, $data] = $this->getFormCascaderMenus($menu['pid']);
            $menu['path'] = $data;
        } else {
            $menu['path'] = explode('/', $menu['path']);
            if (is_array($menu['path'])) {
                $menu['path'] = array_map(function ($item) {
                    return (int)$item;
                }, $menu['path']);
            }
        }

        return $menu;
    }

    /**
     * 注释：删除菜单
     * 创建人：Jack
     * 创建时间：2023/8/1 15:06
     * @param int $id
     * @return bool|mixed
     */
    public function delete(int $id)
    {
        $ids = $this->dao->column(['pid' => $id], 'id');
        if (count($ids)) {
            foreach ($ids as $value) {
                $this->delete($value);
            }
        }

        return $this->dao->update($id, ['is_delete' => 1]);
    }

    /**
     * 注释：获取添加角色权限
     * 创建人：Jack
     * 创建时间：2023/8/1 10:12
     * @param     $roles
     * @param int $is_show
     * @return array
     */
    public function getMenus($roles, int $is_show = 1): array
    {
        $field = ['menu_name', 'pid', 'id'];
        $where = ['is_delete' => 0, 'is_show_path' => 1];
        if ($is_show) $where['is_show'] = 1;
        if (!$roles) {
            $menus = $this->dao->getMenusRoule($where, $field);
        } else {
            /** @var SystemRoleServices $service */
            $service = app()->make(SystemRoleServices::class);
            // 拼接有长度限制
//            $ids = $service->value([['id', 'in', $roles]], 'GROUP_CONCAT(rules) as ids');
            $roles = is_string($roles) ? explode(',', $roles) : $roles;
            $ids = $service->getRoleIds($roles);
            $menus = $this->dao->getMenusRoule(['rule' => $ids] + $where, $field);
        }
        return $this->tidyMenuTier(false, $menus);
    }

    /**
     * 注释：组合菜单数据
     * 创建人：Jack
     * 创建时间：2023/8/2 14:49
     * @param       $adminFilter
     * @param       $menusList
     * @param int   $pid
     * @param array $navList
     * @return array
     */
    public function tidyMenuTier($adminFilter, $menusList, int $pid = 0, array $navList = []): array
    {
        foreach ($menusList as $k => $menu) {
            $menu = $menu->getData();
            $menu['title'] = $menu['menu_name'];
            unset($menu['menu_name']);
            if ($menu['pid'] == $pid) {
                unset($menusList[$k]);
                $menu['children'] = $this->tidyMenuTier($adminFilter, $menusList, $menu['id']);
                if ($pid == 0 && !count($menu['children'])) continue;
                if ($menu['children']) $menu['expand'] = true;
                $navList[] = $menu;
            }
        }

        return $navList;
    }

    /**
     * 注释：getFormCascaderMenus
     * 创建人：Jack
     * 创建时间：2023/8/1 11:05
     * @param int $value
     * @param int $type
     * @return array
     */
    protected function getFormCascaderMenus(int $value = 0, int $type = 1)
    {
        $menuList = $this->dao->getMenusRoule(['is_delete' => 0, 'type' => $type], ['id as value', 'pid', 'menu_name as label']);
        $menuList = $this->getMenusData($menuList);
        if ($value) {
            $data = get_tree_value($menuList, $value);
        } else {
            $data = [];
        }
        return [get_tree_children($menuList, 'children', 'value'), array_reverse($data)];
    }

}
